#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
服务管理器
负责服务类对象的创建、管理和调用
"""

import json
import time
from typing import Dict, Any, List, Optional, Type
from dataclasses import dataclass
from enum import Enum

from sqlalchemy.orm import Session
from sqlalchemy import and_, or_

from models.service_class import ServiceClass, ServiceInstance, ServiceUsageLog, DEFAULT_SERVICE_CLASSES
from models.prompt_template import PromptTemplate, PromptParameter, ParameterType
from core.database import SessionLocal
from core.logging_config import get_logger
from core.exceptions import AIServiceError
from services.ai_service_factory import ai_service_factory, ServiceType, ServiceConfig, ServiceRequest, ServiceResponse

logger = get_logger("service_manager")


class ServiceExecutionStatus(str, Enum):
    """服务执行状态"""
    PENDING = "pending"
    RUNNING = "running"
    SUCCESS = "success"
    FAILED = "failed"
    TIMEOUT = "timeout"


@dataclass
class ServiceExecutionResult:
    """服务执行结果"""
    success: bool
    data: Any = None
    error_message: str = None
    execution_time: float = 0.0
    token_count: int = 0
    cost: str = None
    status: ServiceExecutionStatus = ServiceExecutionStatus.PENDING


class ServiceManager:
    """服务管理器"""
    
    def __init__(self):
        """初始化服务管理器"""
        self._service_cache: Dict[str, ServiceClass] = {}
        self._instance_cache: Dict[int, ServiceInstance] = {}
        self.initialize_default_services()
        
    def initialize_default_services(self):
        """初始化默认服务"""
        logger.info("开始初始化默认服务")
        
        db = SessionLocal()
        try:
            # 创建默认服务类
            for service_config in DEFAULT_SERVICE_CLASSES:
                self._create_default_service_class(db, service_config)
            
            db.commit()
            logger.info("默认服务初始化完成")
            
        except Exception as e:
            db.rollback()
            logger.error(f"默认服务初始化失败: {str(e)}")
            raise
        finally:
            db.close()
    
    def _create_default_service_class(self, db: Session, service_config: Dict[str, Any]):
        """创建默认服务类"""
        service_id = service_config["service_id"]
        
        # 检查是否已存在
        existing_service = db.query(ServiceClass).filter(
            ServiceClass.service_id == service_id
        ).first()
        
        if existing_service:
            logger.info(f"服务 {service_id} 已存在，跳过创建")
            return
        
        # 创建提示词模板
        prompt_template = self._create_prompt_template(db, service_config)
        if not prompt_template:
            logger.warning(f"无法为服务 {service_id} 创建提示词模板")
            return
        
        # 创建服务类
        service_class = ServiceClass(
            service_id=service_id,
            name=service_config["name"],
            description=service_config["description"],
            category=service_config["category"],
            provider=service_config["provider"],
            model_code=service_config["model_code"],
            prompt_template_id=prompt_template.id,
            is_active=service_config["is_active"],
            config=service_config["config"]
        )
        
        db.add(service_class)
        db.flush()  # 获取ID
        
        logger.info(f"创建服务类: {service_id} - {service_config['name']}")
    
    def _create_prompt_template(self, db: Session, service_config: Dict[str, Any]) -> Optional[PromptTemplate]:
        """创建提示词模板"""
        service_id = service_config["service_id"]
        
        # 根据服务ID获取提示词配置
        prompt_config = self._get_prompt_config_by_service_id(service_id)
        if not prompt_config:
            return None
        
        # 创建提示词模板
        template = PromptTemplate(
            name=prompt_config["name"],
            description=prompt_config["description"],
            content=prompt_config["content"],
            category="ai_analysis",
            output_format=prompt_config["output_format"],
            output_schema=prompt_config["output_schema"],
            enable_thinking=prompt_config["enable_thinking"],
            is_system=True,
            service_type=service_id
        )
        
        db.add(template)
        db.flush()  # 获取ID
        
        # 创建参数
        for param_config in prompt_config.get("parameters", []):
            parameter = PromptParameter(
                template_id=template.id,
                name=param_config["name"],
                description=param_config.get("description", ""),
                param_type=param_config.get("type", ParameterType.STRING),
                is_required=param_config.get("required", False),
                default_value=param_config.get("default_value", ""),
                display_name=param_config.get("display_name", param_config["name"]),
                placeholder=param_config.get("placeholder", ""),
                help_text=param_config.get("help_text", "")
            )
            db.add(parameter)
        
        return template
    
    def _get_prompt_config_by_service_id(self, service_id: str) -> Optional[Dict[str, Any]]:
        """根据服务ID获取提示词配置"""
        prompt_configs = {
            "extract_info": {
                "name": "地址抽取",
                "description": "从信访内容中抽取街道、区县、详细地址、详细对象等信息",
                "content": """# 角色
你是一个环保信访投诉智能分析助手，善于从信访投诉信息中提取有用信息。

## 信访投诉
### 诉求内容
{{xfnr}}

### 概况
{{ts_gk}}

### 问题属地
{{ts_xzq}}
- 区县市： {{ts_qxs}}
- 乡镇街道： {{ts_jd}}

### 受信人地址
{{ts_dz}}

### 信访去向单位
{{ts_qxdw}}

### 信访处理时的备注
{{ts_bz}}

### 信访答复内容
{{ts_dfnr}}

## 要求
1. 根据[信访投诉]信息，提取被投诉对象、所在区县、所在街道、所在具体地址及关键词，常见被投诉对象是xx企业、xx商铺、xx小区、xx工地、xx小区住户等等。
2. 不允许在答案中添加编造成分，禁止出现注释和解释。""",
                "output_format": "json",
                "enable_thinking": False,
                "output_schema": """## 输出
请按照以下格式输出json数据：```json
{"ds": str='被投诉对象的地市，如果无法确定则为"无"，不允许为山东省'
"qx": str='被投诉对象的区县，如果无法确定则为"无"，不允许为宁波市',
"jd": str='被投诉对象的街道，如果无法确定则为"无"，不允许为区县',
"dz": dict={'text': '被投诉对象的具体地址，不包含区县和街道信息','words':['方便检索的简称、别名，用英文逗号分割']}
"dx": dict={'text': '被投诉对象', 'words':['方便检索的简称、别名，用英文逗号分割']}}```""",
                "parameters": [
                    {
                        "name": "xfnr",
                        "description": "诉求内容",
                        "type": "string",
                        "required": True,
                        "display_name": "诉求内容",
                        "placeholder": "请输入诉求内容"
                    },
                    {
                        "name": "ts_gk",
                        "description": "概况",
                        "type": "string",
                        "required": False,
                        "display_name": "概况",
                        "placeholder": "请输入概况"
                    },
                    {
                        "name": "ts_xzq",
                        "description": "问题属地",
                        "type": "string",
                        "required": False,
                        "display_name": "问题属地",
                        "placeholder": "请输入问题属地"
                    },
                    {
                        "name": "ts_qxs",
                        "description": "区县市",
                        "type": "string",
                        "required": False,
                        "display_name": "区县市",
                        "placeholder": "请输入区县市"
                    },
                    {
                        "name": "ts_jd",
                        "description": "乡镇街道",
                        "type": "string",
                        "required": False,
                        "display_name": "乡镇街道",
                        "placeholder": "请输入乡镇街道"
                    },
                    {
                        "name": "ts_dz",
                        "description": "受信人地址",
                        "type": "string",
                        "required": False,
                        "display_name": "受信人地址",
                        "placeholder": "请输入受信人地址"
                    },
                    {
                        "name": "ts_qxdw",
                        "description": "信访去向单位",
                        "type": "string",
                        "required": False,
                        "display_name": "信访去向单位",
                        "placeholder": "请输入信访去向单位"
                    },
                    {
                        "name": "ts_bz",
                        "description": "信访处理时的备注",
                        "type": "string",
                        "required": False,
                        "display_name": "信访处理时的备注",
                        "placeholder": "请输入备注"
                    },
                    {
                        "name": "ts_dfnr",
                        "description": "信访答复内容",
                        "type": "string",
                        "required": False,
                        "display_name": "信访答复内容",
                        "placeholder": "请输入答复内容"
                    }
                ]
            },
            "specify_analysis": {
                "name": "规范分析",
                "description": "根据定义判断回复内容是否合规",
                "content": """# 角色
你是一个工作规范检查师，需要对工作回复内容进行核对，依据【判断规则】判断回复内容是否合规。

## 判断规则
1、被举报对象基本情况。包括企业名称、地址及周边现状、环保手续、污染物产生环节、污染防治设施等。
2、现场检查情况。包括进入现场检查时间;被举报对象生产状况;污染物处理设施运行情况;污染物排放情况;有监测报告的，明确监测数据及相应排放标准;举报件有能够反映现场污染现状照片的，要针对照片反映情况进行排查并详细说明原因和排查结果等。
3、调查处理情况。1包括被举报对象是否存在环境违法行为，原因并说明相应处理措施;下一步监管措施或工作计划;现场办理人员及联系电话等。
4、对举报投诉是否属实表述。
5、答复举报人情况。答复内容、答复方式和满意情况。

## 回复样例
尊敬的某某女士/先生:
您好!您于2月20日反映的关于奉化区滨海新区滨沙路28号宁波鸿越金属制品有限公司噪声污染问题已收悉，经生态环境泰化分局调查了解，现将答复意见回复如下:
一、基本情况
宁波鸿越金属制品有限公司，位于奉化区滨海新区滨沙路28号，主要从事金属制品加工生产，主要生产设备:冲床30台、焊机5台及其他生产辅助设备若干，主要生产工艺:原材料-冲压-切边-焊接-成品，建设项目有环评验收等相关手续。
二、调查情况
2025年2月24日，我分局执法人员对该公司进行检查，现场该公司生产中，生产车间做有密闭措施，厂区内未听见有较大生产音，现场该公司提供有委托第三方噪声检测的报告，检测结果合格，反映情况不实
三、处理意见
要求该公司加强管理，做好生产车间的隔音密闭措施。
上述情况我单位工作人员已电话告知您，您表示满意。
经办人:XXX，联系电话:XXX
感谢您对生态环境工作的关注和支持!
宁波市生态环境局XX分局

## 回复内容
{{ts_dfnr}}""",
                "output_format": "json",
                "enable_thinking": False,
                "output_schema": """## 输出
根据判断结果，结果按照json格式输出：```json
{"是否规范":str="是否合规判断结果，合规/不合规",
"判断依据":str="合规判断的依据"}```""",
                "parameters": [
                    {
                        "name": "ts_dfnr",
                        "description": "答复内容",
                        "type": "string",
                        "required": True,
                        "display_name": "答复内容",
                        "placeholder": "请输入答复内容"
                    }
                ]
            },
            "sentiment_analysis": {
                "name": "情感分析",
                "description": "根据定义判断信访内容的情感",
                "content": """# 角色
你是一个情感分析和主题词摘要提取专家，擅长分析投诉内容中存在的行为、语言来判断情感倾向，根据情感定义进行判断并给出判断说明，并从中提取主题词和摘要内容。

## 技能

### 情感分析
1. 轻度：平白叙述污染内容和事情，积极请求解决问题等
2. 中度：带有愤怒、不耐烦等负面情感词的内容
3. 重度：内容中有涉及要去市里、省里、进京上访，一直反映、投诉，团体投诉，拉条幅，暴力行为，砍人等

### 主题词摘要提取
1. 生成投诉内容的简要摘要。
2. 从投诉内容中抽取关键词汇。

## 任务
1、阅读并理解投诉内容
2、执行技能情感分析的能力，分析情感类型并给出评判理由
3、执行技能主题词摘要提取能力，输出摘要和主题词

## 信访内容
{{xfnr}}""",
                "output_format": "json",
                "enable_thinking": False,
                "output_schema": """## 输出
结果输出为json格式，```json
{"情感类型":str="愤怒程度：轻度、中度、重度",
"判断理由":str="情感判断的理由",
"摘要":str="生成的摘要内容",
"关键词":str="从内容种抽取的关键词"}```""",
                "parameters": [
                    {
                        "name": "xfnr",
                        "description": "信访内容",
                        "type": "string",
                        "required": True,
                        "display_name": "信访内容",
                        "placeholder": "请输入信访内容"
                    }
                ]
            }
        }
        
        return prompt_configs.get(service_id)
    
    def get_service_class(self, service_id: str) -> Optional[ServiceClass]:
        """获取服务类"""
        # 先从缓存查找
        if service_id in self._service_cache:
            return self._service_cache[service_id]
        
        # 从数据库查找
        db = SessionLocal()
        try:
            service_class = db.query(ServiceClass).filter(
                ServiceClass.service_id == service_id,
                ServiceClass.is_active == True
            ).first()
            
            if service_class:
                self._service_cache[service_id] = service_class
                
            return service_class
        finally:
            db.close()
    
    def create_service_instance(self, service_id: str, user_id: int, instance_name: str, instance_config: Dict[str, Any] = None) -> Optional[ServiceInstance]:
        """创建服务实例"""
        service_class = self.get_service_class(service_id)
        if not service_class:
            raise AIServiceError(f"服务 {service_id} 不存在")
        
        db = SessionLocal()
        try:
            instance = ServiceInstance(
                service_class_id=service_class.id,
                user_id=user_id,
                instance_name=instance_name,
                instance_config=instance_config or {},
                is_active=True
            )
            
            db.add(instance)
            db.commit()
            db.refresh(instance)
            
            # 缓存实例
            self._instance_cache[instance.id] = instance
            
            return instance
        except Exception as e:
            db.rollback()
            raise AIServiceError(f"创建服务实例失败: {str(e)}")
        finally:
            db.close()
    
    def execute_service(self, service_id: str, input_data: Dict[str, Any], user_id: int = None) -> ServiceExecutionResult:
        """执行服务"""
        start_time = time.time()
        
        try:
            # 获取服务类
            service_class = self.get_service_class(service_id)
            if not service_class:
                return ServiceExecutionResult(
                    success=False,
                    error_message=f"服务 {service_id} 不存在",
                    execution_time=time.time() - start_time,
                    status=ServiceExecutionStatus.FAILED
                )
            
            # 创建服务请求
            request = ServiceRequest(
                service_type=ServiceType.AI_ANALYSIS,
                data={
                    "service_id": service_id,
                    "input_data": input_data,
                    "service_config": service_class.get_service_config()
                }
            )
            
            # 执行服务
            response = ai_service_factory.process_request(request)
            
            if response.success:
                result = ServiceExecutionResult(
                    success=True,
                    data=response.data,
                    execution_time=response.processing_time,
                    token_count=response.data.get("token_count", 0),
                    cost=response.data.get("cost"),
                    status=ServiceExecutionStatus.SUCCESS
                )
                
                # 更新使用统计
                service_class.update_usage_stats()
                
            else:
                result = ServiceExecutionResult(
                    success=False,
                    error_message=response.error_message,
                    execution_time=response.processing_time,
                    status=ServiceExecutionStatus.FAILED
                )
            
            # 记录使用日志
            self._log_service_usage(service_class.id, None, user_id, input_data, result)
            
            return result
            
        except Exception as e:
            logger.error(f"执行服务 {service_id} 失败: {str(e)}")
            return ServiceExecutionResult(
                success=False,
                error_message=str(e),
                execution_time=time.time() - start_time,
                status=ServiceExecutionStatus.FAILED
            )
    
    def _log_service_usage(self, service_class_id: int, service_instance_id: int, user_id: int, request_data: Dict[str, Any], result: ServiceExecutionResult):
        """记录服务使用日志"""
        db = SessionLocal()
        try:
            log = ServiceUsageLog(
                service_class_id=service_class_id,
                service_instance_id=service_instance_id,
                user_id=user_id,
                request_data=request_data,
                response_data=result.data if result.success else None,
                execution_time=int(result.execution_time * 1000),
                token_count=result.token_count,
                cost=result.cost,
                status=result.status.value,
                error_message=result.error_message
            )
            
            db.add(log)
            db.commit()
        except Exception as e:
            logger.error(f"记录服务使用日志失败: {str(e)}")
        finally:
            db.close()
    
    def get_service_statistics(self, service_id: str = None) -> Dict[str, Any]:
        """获取服务统计信息"""
        db = SessionLocal()
        try:
            query = db.query(ServiceClass)
            
            if service_id:
                query = query.filter(ServiceClass.service_id == service_id)
            
            services = query.all()
            
            stats = {}
            for service in services:
                stats[service.service_id] = {
                    "name": service.name,
                    "usage_count": service.usage_count,
                    "last_used_at": service.last_used_at.isoformat() if service.last_used_at else None,
                    "status": service.status,
                    "provider": service.provider,
                }
            
            return stats
        finally:
            db.close()
    
    def health_check(self) -> Dict[str, Any]:
        """健康检查"""
        db = SessionLocal()
        try:
            total_services = db.query(ServiceClass).count()
            active_services = db.query(ServiceClass).filter(ServiceClass.is_active == True).count()
            
            return {
                "healthy": True,
                "total_services": total_services,
                "active_services": active_services,
                "cached_services": len(self._service_cache),
                "cached_instances": len(self._instance_cache)
            }
        except Exception as e:
            logger.error(f"健康检查失败: {str(e)}")
            return {
                "healthy": False,
                "error": str(e)
            }
        finally:
            db.close()


# 创建全局服务管理器实例
service_manager = ServiceManager()
